home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Texteditors / XDME / Src / text.c < prev    next >
C/C++ Source or Header  |  1996-09-26  |  29KB  |  1,453 lines

  1. /******************************************************************************
  2.  
  3.     MODUL
  4.     text.c
  5.  
  6.     DESCRIPTION
  7.  
  8.     NOTES
  9.  
  10.     BUGS
  11.  
  12.     TODO
  13.  
  14.     EXAMPLES
  15.  
  16.     SEE ALSO
  17.  
  18.     INDEX
  19.  
  20.     HISTORY
  21.     04. Oct 1992    ada created
  22.  
  23. ******************************************************************************/
  24.  
  25. /**************************************
  26.         Includes
  27. **************************************/
  28. #include "defs.h"
  29.  
  30.  
  31. /**************************************
  32.         Globale Variable
  33. **************************************/
  34.  
  35.  
  36. /**************************************
  37.       Interne Defines & Strukturen
  38. **************************************/
  39.  
  40.  
  41. /**************************************
  42.         Interne Variable
  43. **************************************/
  44.  
  45.  
  46. /**************************************
  47.        Interne Prototypes
  48. **************************************/
  49. Prototype ED    * uninit_init         (ED *);
  50. Prototype int      setpen         (Line, Column);
  51. Prototype WORD      inversemode         (int);
  52. Prototype void      text_cursor         (int);
  53. Prototype int      text_init         (ED *, WIN *, struct NewWindow *);
  54. Prototype BOOL      text_switch         (struct Window *);
  55. Prototype BOOL      text_sync         (void);
  56. Prototype BOOL      text_adjust         (BOOL);
  57. Prototype void      text_load         (void);
  58. Prototype int      text_colno         (void);
  59. Prototype int      text_lineno         (void);
  60. Prototype int      text_lines         (void);
  61. Prototype int      text_cols         (void);
  62. Prototype int      text_imode         (void);
  63. Prototype int      text_tabsize         (void);
  64. Prototype UBYTE * text_name         (void);
  65. Prototype void      text_uninit         (void);
  66. Prototype void      text_position      (int, int);
  67. Prototype void      text_redisplaycurrline (void);
  68. Prototype void      do_redisplay         (void);
  69. Prototype void      text_redisplay     (void);
  70. Prototype void      text_write         (UBYTE *);
  71. Prototype void      text_displayseg     (int, int);
  72. Prototype void      text_redraw_cmdline     (void);
  73. Prototype void      text_redrawblock     (BOOL);
  74. Prototype void      redraw_text         (Line, Line);
  75. Prototype void      redraw_textlineseg     (Line, Column, Column);
  76. Prototype void      redraw_lineseg     (UBYTE *, UWORD, Column, Column);
  77.  
  78.  
  79. /*****************************************************************************
  80.  
  81.     NAME
  82.     uninit_init
  83.  
  84.     PARAMETER
  85.     ED * ep;
  86.  
  87.     RETURN
  88.     ED * new_ep;
  89.  
  90.     DESCRIPTION
  91.     Resets an editor-struct.
  92.  
  93. ******************************************************************************/
  94.  
  95. ED * uninit_init (ED * ep)
  96. {
  97.     FONT      * font;
  98.     BPTR        lock   = DupLock (ep->dirlock);
  99.     WIN       * win;
  100.     struct Gadget * gadg;
  101.     int         bufsiz = CONFIG_SIZE;
  102.     char      * buf    = malloc (bufsiz);
  103.  
  104.     /* get buffer for config */
  105.     if (!buf)
  106.     {
  107.     nomemory ();
  108.  
  109.     warn ("Out of memory !");
  110.  
  111.     return (NULL);
  112.     }
  113.  
  114.     movmem (&ep->beginconfig, buf, bufsiz);
  115.  
  116.     /* remember window, font and gadget */
  117.     win     = ep->win;
  118.     font    = ep->font;
  119.     gadg    = ep->propgad;
  120.     ep->font    = NULL;
  121.  
  122.     /* throw anything away */
  123.     text_uninit ();
  124.  
  125.     /* init editor */
  126.     text_init (Ep, NULL, NULL);
  127.  
  128.     /* switch to new one */
  129.     ep = Ep;
  130.  
  131.     /* close font if there is one */
  132.     if (ep->font)
  133.     CloseFont (ep->font);
  134.  
  135.     /* reset window */
  136.     ep->win  = win;
  137.  
  138.     /* set new font */
  139.     if (ep->font = font)
  140.     {
  141.     SetFont (ep->win->RPort, font);
  142.     set_window_params ();
  143.     }
  144.  
  145.     /* set gadget */
  146.     ep->propgad = gadg;
  147.  
  148.     /* copy config back */
  149.     movmem (buf, &ep->beginconfig, bufsiz);
  150.  
  151.     /* no modifications. Set cursor to beginning */
  152.     ep->modified = 0;
  153.     ep->line     = ep->topline = 0;
  154.  
  155.     /* create new lock */
  156.     UnLock (ep->dirlock);
  157.     ep->dirlock = (long)lock;
  158.  
  159.     /* free buffer */
  160.     free (buf);
  161.  
  162.     return (ep);
  163. } /* uninit_init */
  164.  
  165.  
  166. /*****************************************************************************
  167.  
  168.     NAME
  169.  
  170.     PARAMETER
  171.  
  172.     RETURN
  173.  
  174.     DESCRIPTION
  175.  
  176. ******************************************************************************/
  177.  
  178. /* Return: Same as is_inblock() ! */
  179. int setpen (Line line, Column column)
  180. {
  181.     ED    * ep   = Ep;
  182.     RP    * rp   = ep->win->RPort;
  183.     WORD  test;
  184.  
  185.     test = is_inblock (line, column);
  186.  
  187.     if (test & BP_INSIDE)
  188.     {
  189.     SetAPen (rp,  BLOCK_FPEN);
  190.     SetBPen (rp,  BLOCK_BPEN);
  191.     SetWrMsk (rp, BLOCK_MASK);
  192.     } else
  193.     {
  194.     SetAPen (rp,  TEXT_FPEN);
  195.     SetBPen (rp,  TEXT_BPEN);
  196.     SetWrMsk (rp, TEXT_MASK);
  197.     }
  198.  
  199.     return (test);
  200. } /* setpen */
  201.  
  202.  
  203. /*****************************************************************************
  204.  
  205.     NAME
  206.  
  207.     PARAMETER
  208.  
  209.     RETURN
  210.  
  211.     DESCRIPTION
  212.  
  213. ******************************************************************************/
  214.  
  215. WORD  inversemode (int n)
  216. {
  217.     RP    * rp = Ep->win->RPort;
  218.     WORD  test;
  219.     UBYTE fgpen;
  220.     UBYTE bgpen;
  221.  
  222.     test = setpen (Ep->line, Ep->column);
  223.  
  224.     if (n)
  225.     {
  226.     fgpen = ~rp->FgPen;
  227.     bgpen = ~rp->BgPen;
  228.  
  229.     SetAPen (rp, bgpen);
  230.     SetBPen (rp, fgpen);
  231.     SetDrMd (rp, JAM2|INVERSVID);
  232.     } else
  233.     SetDrMd (rp, JAM2);
  234.  
  235.     SetWrMsk (rp, 0xFF);
  236.  
  237.     return ((WORD)(test & BP_INSIDE));
  238. } /* inversemode */
  239.  
  240.  
  241. /*****************************************************************************
  242.  
  243.     NAME
  244.  
  245.     PARAMETER
  246.  
  247.     RETURN
  248.  
  249.     DESCRIPTION
  250.  
  251. ******************************************************************************/
  252.  
  253. int text_init (ED * oldep, WIN * win, struct NewWindow * nw)
  254. {
  255.     ED * ep;
  256.  
  257.     if (!(ep = (ED *)allocb (sizeof(ED))) )
  258.     return (0);
  259.  
  260.     setmem (ep, sizeof(ED), 0);
  261.     ep->win = win;
  262.  
  263.     if (oldep)
  264.     {
  265.     ep->dirlock = (long)DupLock (oldep->dirlock);
  266.  
  267.     movmem (&oldep->beginconfig, &ep->beginconfig, CONFIG_SIZE);
  268.  
  269.     if (oldep->font)
  270.     {
  271.         ep->font = oldep->font;
  272.         ep->font->tf_Accessors ++;
  273.  
  274.         if (win)
  275.         SetFont (win->RPort, ep->font);
  276.     }
  277.  
  278.     /* change oldep to "last editor" to have the iconified window
  279.        positioned right */
  280.     oldep = GetTail ((LIST *)&DBase);
  281.  
  282.     if (oldep->iconmode)
  283.     {
  284.         ep->config.iwinx = oldep->win->LeftEdge;
  285.         ep->config.iwiny = oldep->win->TopEdge;
  286.     } else
  287.     {
  288.         ep->config.iwinx = oldep->config.iwinx;
  289.         ep->config.iwiny = oldep->config.iwiny;
  290.     }
  291.  
  292.     ep->config.iwinx += TextLength (oldep->win->RPort, oldep->name,
  293.                 strlen (oldep->name)) + 60;
  294.  
  295.     if (ep->config.iwinx > oldep->win->WScreen->Width)
  296.     {
  297.         ep->config.iwinx = 0;
  298.  
  299.         if(Ep->win->WScreen->Font != NULL)
  300.         /* height */
  301.         ep->config.iwiny += oldep->win->WScreen->Font->ta_YSize + 3;
  302.         else
  303.         ep->config.iwiny += GfxBase->DefaultFont->tf_YSize + 3;
  304.     }
  305.     }
  306.     else
  307.     {
  308.     PROC * proc = (PROC *)FindTask (NULL);
  309.  
  310.     ep->dirlock = (long)DupLock (proc->pr_CurrentDir);
  311.  
  312.     loadconfig (ep);
  313.     }
  314.  
  315.     ep->lines      = 1;
  316.     ep->maxlines  = 32;
  317.     ep->list      = (UBYTE **)alloclptr (ep->maxlines);
  318.     SETLINE(ep,0,allocline (1));
  319.  
  320.     Current[0] = Clen = 0;
  321.  
  322.     AddTail ((LIST *)&DBase, (NODE *)ep);
  323.     ep->node.ln_Name = ep->name;
  324.     ep->keytable  = currenthash ();      /* PATCH_NULL [01 Feb 1993] : added */
  325.     ep->menustrip = currentmenu ();      /* PATCH_NULL [01 Feb 1993] : added */
  326.  
  327.     strcpy ((char *)ep->name, "unnamed");
  328.     Ep = ep;    /* no switch_ed() here ! */
  329.  
  330.     strcpy (ep->wtitle, "  OK  ");
  331.  
  332.     if (win)
  333.     text_cursor (1);
  334.  
  335.     if (nw)
  336.     {
  337.     if (!ep->iconmode && ep->win)
  338.     {
  339.         nw->LeftEdge = ep->win->LeftEdge;
  340.         nw->TopEdge  = ep->win->TopEdge;
  341.         nw->Width     = ep->win->Width;
  342.         nw->Height     = ep->win->Height;
  343.     } else
  344.     {
  345.         if (ep->config.winwidth && ep->config.winheight)
  346.         {
  347.         nw->LeftEdge = ep->config.winx;
  348.         nw->TopEdge  = ep->config.winy;
  349.         nw->Width    = ep->config.winwidth;
  350.         nw->Height   = ep->config.winheight;
  351.         } else
  352.         {
  353.         nw->LeftEdge = 0;
  354.         nw->TopEdge  = 0;
  355.         nw->Width    = 640;
  356.         nw->Height   = 200;
  357.         }
  358.     }
  359.  
  360.     nw->DetailPen = TEXT_BPEN;
  361.     nw->BlockPen  = TEXT_FPEN;
  362.     }
  363.  
  364.     return (1);
  365. } /* text_init */
  366.  
  367.  
  368. /*****************************************************************************
  369.  
  370.     NAME
  371.     text_switch
  372.  
  373.     PARAMETER
  374.     WIN * win;        The window to switch to.
  375.  
  376.     RETURN
  377.     BOOL found;        Was the change successful ?
  378.  
  379.     DESCRIPTION
  380.     Searches for the specified window and makes the editor with that
  381.     window active.
  382.  
  383. ******************************************************************************/
  384.  
  385. BOOL text_switch (WIN * win)
  386. {
  387.     ED * ep;
  388.  
  389.     /* look for that window */
  390.  
  391.     for (ep=(ED *)GetHead(&DBase); ep; ep=(ED *)GetSucc((struct Node *)ep))
  392.     {
  393.     if (ep->win == win)
  394.         break;
  395.     }
  396.  
  397.     return (switch_ed (ep));
  398. } /* text_switch */
  399.  
  400.  
  401. /*****************************************************************************
  402.  
  403.     NAME
  404.     text_sync
  405.  
  406.     PARAMETER
  407.     void
  408.  
  409.     RETURN
  410.     BOOL redraw;        Did text_sync() a screen-refresh ?
  411.  
  412.     DESCRIPTION
  413.     copy current line to list of lines and say, if screen-update
  414.     is neccessary. Furthermore, Current is filled with spaces upto
  415.     the current column.
  416.  
  417. ******************************************************************************/
  418.  
  419. BOOL text_sync (void)
  420. {
  421.     ED      * ep       = Ep;
  422. //    char    redraw = 0;
  423.     WORD    len;
  424.     UBYTE * ptr;
  425.     UBYTE * line;
  426.  
  427.     /* remove trailing spaces */
  428.     len = strlen ((char *)Current)-1;
  429.     ptr = Current + len;
  430.  
  431.     while (len && *ptr == ' ')
  432.     {
  433.     len --;
  434.     ptr --;
  435.     }
  436.  
  437.     if (*ptr == ' ')
  438.     *ptr = 0;
  439.     else
  440.     {
  441.     ptr[1] = 0;
  442.     len ++;
  443.     }
  444.  
  445.     /* Line length */
  446.     Clen = len;
  447.  
  448.     if (!globalflags.Comlinemode)
  449.     {
  450.     WORD  len_in_blocks, clen_in_blocks;
  451.  
  452.     line = GETTEXT(ep,ep->line);
  453.     len = strlen ((char *)line);
  454.  
  455.     /* Find out how many blocks (*8) we use and how many we need */
  456.     len_in_blocks  =  (len + 8) & ~7;
  457.     clen_in_blocks = (Clen + 8) & ~7;
  458.  
  459.     /* This was highly wasting memory. OS is always padding Alloc's
  460.        to 8 Bytes. If the length of the line is still within one
  461.        block but has changed we freed and allocated new memory.
  462.        This guranteed to fragment memory.
  463.  
  464.        Just use the old version and edit some large text. Use avail,
  465.        save & reload text and "avail" again. The you'll see what I mean.
  466.        This is fixed now. */
  467.  
  468.     /* I must not use strcpy() if the line was empty since empty
  469.        lines are handled differently, i.e. they use static memory.
  470.        Only allocate new, if the line was empty or if the size in
  471.        blocks has changed, i.e. we need one more or less block of
  472.        memory (see AllocMem() in Amiga-ROM-Kernel-Ref.-Manual about
  473.        blocks). */
  474.     if ((!len && Clen) || len_in_blocks != clen_in_blocks)
  475.     {
  476.         if (ptr = allocline(Clen+1))
  477.         {
  478.  
  479. #ifdef DEBUG_MEM_H
  480.     printf ("Allocated at %08x\n", ptr);
  481. #endif
  482.  
  483.         ep->modified = 1;
  484.         globalflags.Overide = 0;
  485.  
  486.         freeline (line);
  487.         SETLINE(ep,ep->line,(LINE)ptr);
  488.  
  489.         strcpy ((char *)ptr, (char *)Current);
  490.         } else
  491.         {
  492.         nomemory ();
  493.         strcpy ((char *)Current, (char *)line);
  494.         }
  495.     } else
  496.     { /* Within one block ... */
  497.         UBYTE * ptr1, * ptr2;
  498.  
  499.         ptr1 = line;
  500.         ptr2 = Current;
  501.  
  502.         /* We need not to copy stuff that's equal ! */
  503.         while (*ptr1 == *ptr2)
  504.         {
  505.         if (!*ptr1)
  506.             break;
  507.  
  508.         ptr1 ++;
  509.         ptr2 ++;
  510.         }
  511.  
  512.         if (*ptr1 != *ptr2)
  513.         {
  514.         ep->modified = 1;
  515.         globalflags.Overide = 0;
  516.  
  517. /*printf ("Lines \nOld `%s'\nNew `%s'\ndiffer at\n%s\n%s", line, Current, ptr1, ptr2); */
  518.  
  519.         strcpy ((char *)ptr1, (char *)ptr2);
  520. /*printf ("New Line `%s'\n", line);*/
  521.         } /* Any changes ? */
  522.     } /* Old block length != new block length */
  523.     } /* if (!Comlinemode) */
  524.  
  525. error:
  526.     return ((BOOL)text_adjust (FALSE));
  527. } /* text_sync */
  528.  
  529.  
  530. /*****************************************************************************
  531.  
  532.     NAME
  533.     text_adjust
  534.  
  535.     PARAMETER
  536.     BOOL force;        TRUE: Redraw screen even if the cursor
  537.                       is visible.
  538.                 FALSE: Draw only, if cursor is not visible.
  539.  
  540.     RETURN
  541.     BOOL did_redraw;
  542.  
  543.     DESCRIPTION
  544.     Make sure the current cursor position is visible.
  545.  
  546. ******************************************************************************/
  547.  
  548. BOOL text_adjust (BOOL force)
  549. {
  550.     if (!Nsu)
  551.     {
  552.     if (Ep->column - Ep->topcolumn >= Columns || Ep->column < Ep->topcolumn)
  553.     {
  554.         force = 1;
  555.  
  556.         Ep->topcolumn = Ep->column - (Columns>>1);
  557.  
  558.         if (Ep->topcolumn < 0)
  559.         Ep->topcolumn = 0;
  560.     }
  561.  
  562.     if (Ep->line - Ep->topline >= Lines || Ep->line < Ep->topline)
  563.     {
  564.         force = 1;
  565.  
  566.         Ep->topline = Ep->line - (Lines>>1);
  567.  
  568.         if (Ep->topline < 0)
  569.         Ep->topline = 0;
  570.     }
  571.  
  572.     /* need I redraw ?? */
  573.     if (force)
  574.         text_redisplay ();
  575.     }
  576.  
  577.     /* pad line with spaces upto cursor */
  578.     while (Ep->column > Clen)
  579.     Current[Clen++] = ' ';
  580.  
  581.     Current[Clen] = '\0';
  582.  
  583.     return (force);
  584. } /* text_adjust */
  585.  
  586.  
  587. /*****************************************************************************
  588.  
  589.     NAME
  590.     text_load
  591.  
  592.     PARAMETER
  593.     void
  594.  
  595.     RETURN
  596.     void
  597.  
  598.     DESCRIPTION
  599.     Load current line into Current. Current is padded with spaces
  600.     if the cursor is to the left.
  601.  
  602. ******************************************************************************/
  603.  
  604.  
  605. void text_load (void)
  606. {
  607.     if (globalflags.Comlinemode)
  608.     return;
  609.  
  610.     strcpy ((char *)Current, GETTEXT(Ep,Ep->line));
  611.  
  612.     Clen = strlen ((char *)Current);
  613.  
  614.     while (Ep->column > Clen)
  615.     Current[Clen++] = ' ';
  616.  
  617.     Current[Clen] = '\0';
  618. } /* text_load */
  619.  
  620.  
  621. /*****************************************************************************
  622.  
  623.     NAME
  624.  
  625.     PARAMETER
  626.  
  627.     RETURN
  628.  
  629.     DESCRIPTION
  630.  
  631. ******************************************************************************/
  632.  
  633. int text_colno (void)
  634. {
  635.     return((int)Ep->column);
  636. } /* text_colno */
  637.  
  638.  
  639. /*****************************************************************************
  640.  
  641.     NAME
  642.  
  643.     PARAMETER
  644.  
  645.     RETURN
  646.  
  647.     DESCRIPTION
  648.  
  649. ******************************************************************************/
  650.  
  651. int text_lineno (void)
  652. {
  653.     return((int)Ep->line+1);
  654. } /* text_lineno */
  655.  
  656.  
  657. /*****************************************************************************
  658.  
  659.     NAME
  660.  
  661.     PARAMETER
  662.  
  663.     RETURN
  664.  
  665.     DESCRIPTION
  666.  
  667. ******************************************************************************/
  668.  
  669. int text_lines (void)
  670. {
  671.     return((int)Ep->lines);
  672. } /* text_lines */
  673.  
  674.  
  675. /*****************************************************************************
  676.  
  677.     NAME
  678.  
  679.     PARAMETER
  680.  
  681.     RETURN
  682.  
  683.     DESCRIPTION
  684.  
  685. ******************************************************************************/
  686.  
  687. int text_cols (void)
  688. {
  689.     return((int)Clen);
  690. } /* text_cols */
  691.  
  692.  
  693. /*****************************************************************************
  694.  
  695.     NAME
  696.  
  697.     PARAMETER
  698.  
  699.     RETURN
  700.  
  701.     DESCRIPTION
  702.  
  703. ******************************************************************************/
  704.  
  705. int text_imode (void)
  706. {
  707.     return((int)Ep->config.insertmode);
  708. } /* text_imode */
  709.  
  710.  
  711. /*****************************************************************************
  712.  
  713.     NAME
  714.  
  715.     PARAMETER
  716.  
  717.     RETURN
  718.  
  719.     DESCRIPTION
  720.  
  721. ******************************************************************************/
  722.  
  723. int text_tabsize (void)
  724. {
  725.     return((int)Ep->config.tabstop);
  726. } /* text_tabsize */
  727.  
  728.  
  729. /*****************************************************************************
  730.  
  731.     NAME
  732.  
  733.     PARAMETER
  734.  
  735.     RETURN
  736.  
  737.     DESCRIPTION
  738.  
  739. ******************************************************************************/
  740.  
  741. UBYTE * text_name (void)
  742. {
  743.     return(Ep->name);
  744. } /* text_name */
  745.  
  746.  
  747. /*****************************************************************************
  748.  
  749.     NAME
  750.  
  751.     PARAMETER
  752.  
  753.     RETURN
  754.  
  755.     DESCRIPTION
  756.  
  757. ******************************************************************************/
  758.  
  759. void text_uninit (void)
  760. {
  761.     ED * ep = Ep;
  762.  
  763.     if (ep)
  764.     {
  765.     markerkill (ep);
  766.     check_stack (ep);
  767.  
  768.     freelist (ep->list, ep->lines);
  769.     FreeMem (ep->list, ep->maxlines * sizeof(LINE));
  770.  
  771.     DelAllVarsFromTree((void **)&ep->textvars); /* PATCH_NULL: local vars have to be freed */
  772.  
  773.     if (ActualBlock.ep == ep)
  774.     {
  775.         ActualBlock.type = BT_NONE;
  776.         ActualBlock.ep = NULL;
  777.     }
  778.  
  779.     Remove ((NODE *)ep);
  780.  
  781.     if (ep->font)
  782.     {
  783.         SetFont (ep->win->RPort, ep->win->WScreen->RastPort.Font);
  784.         CloseFont (ep->font);
  785.     }
  786.  
  787.     UnLock (ep->dirlock);
  788.     FreeMem (ep, sizeof(ED));
  789.  
  790.     if (ep = (ED *)GetHead (&DBase))
  791.     {
  792.         Ep = NULL;
  793.  
  794.         switch_ed (ep);
  795.  
  796.         text_load ();
  797.     } else
  798.         Ep = NULL;
  799.     }
  800. } /* text_uninit */
  801.  
  802.  
  803. /*****************************************************************************
  804.  
  805.     NAME
  806.  
  807.     PARAMETER
  808.  
  809.     RETURN
  810.  
  811.     DESCRIPTION
  812.  
  813. ******************************************************************************/
  814.  
  815. void text_cursor (int n)
  816. {
  817.     ED    * ep   = Ep;
  818.     RP    * rp   = ep->win->RPort;
  819.  
  820.     if (Ep->iconmode || Nsu)
  821.     return;
  822.  
  823.     movetocursor ();
  824.     inversemode (n);
  825.  
  826.     if (Current[ep->column])
  827.     {
  828.     Text (rp, Current + ep->column, 1);
  829.     } else
  830.     {
  831.     Text (rp, (STRPTR)" ", 1);
  832.     }
  833.  
  834.     if (n && globalflags.FollowCursor)
  835.     do_makecursorvisible ();
  836.  
  837.     inversemode (0);
  838.  
  839.     /* SetBPen (rp, TEXT_BPEN);
  840.     SetWrMsk (rp, -1); */
  841. } /* text_cursor */
  842.  
  843.  
  844. /*****************************************************************************
  845.  
  846.     NAME
  847.  
  848.     PARAMETER
  849.  
  850.     RETURN
  851.  
  852.     DESCRIPTION
  853.  
  854. ******************************************************************************/
  855.  
  856. void text_position (int col, int row)
  857. {
  858.     ED    * ep     = Ep;
  859.     WORD  column,
  860.       line;
  861.  
  862.     text_sync ();
  863.  
  864.     column = ep->topcolumn + col;
  865.  
  866.     if (column > MAXLINELEN-1)
  867.     column = MAXLINELEN-1;
  868.  
  869.     if (column < 0)
  870.     column = 0;
  871.  
  872.     line = ep->topline + row;
  873.  
  874.     if (line >= ep->lines)
  875.     line = ep->lines - 1;
  876.  
  877.     if (line < 0)
  878.     line = 0;
  879.  
  880.     ep->column = column;
  881.     ep->line = line;
  882.  
  883.     text_load ();
  884.     text_adjust (FALSE);
  885. } /* text_position */
  886.  
  887.  
  888. /*****************************************************************************
  889.  
  890.     NAME
  891.     text_displayseg
  892.  
  893.     PARAMETER
  894.     int start;
  895.     int lines;
  896.  
  897.     RETURN
  898.     void
  899.  
  900.     DESCRIPTION
  901.  
  902. ******************************************************************************/
  903.  
  904. void text_displayseg (int start, int lines)
  905. {
  906.     ED * ep = Ep;
  907.  
  908.     if (Nsu || ep->iconmode) return;
  909.  
  910.     if (globalflags.Comlinemode)
  911.     {
  912.     text_redraw_cmdline ();
  913.     } else
  914.     {
  915.     Line   start_line;
  916.  
  917.     start_line = start + ep->topline;
  918.  
  919.     redraw_block (TRUE, start_line, ep->topcolumn,
  920.             start_line + lines-1, ep->topcolumn + Columns-1);
  921.  
  922.     prop_adj ();
  923.     } /* !Comlinemode */
  924. } /* text_displayseg */
  925.  
  926.  
  927. /*****************************************************************************
  928.  
  929.     NAME
  930.     text_redraw_cmdline
  931.  
  932.     PARAMETER
  933.     void
  934.  
  935.     RETURN
  936.     void
  937.  
  938.     DESCRIPTION
  939.  
  940. ******************************************************************************/
  941.  
  942. void text_redraw_cmdline (void)
  943. {
  944.     RP * rp = Ep->win->RPort;
  945.     int  len;
  946.     int  topline = Ep->line - Ep->topline;
  947.  
  948.     /* Clear back */
  949.     SetAPen  (rp, TEXT_BPEN);
  950.     SetWrMsk (rp, 0xFF);
  951.     RectFill (rp, Xbase, ROW(topline), Xpixs, Ypixs);
  952.  
  953.     /* Write text */
  954.     SetAPen (rp, TEXT_FPEN);
  955.     SetBPen (rp, TEXT_BPEN);
  956.  
  957.     len = Clen - Ep->topcolumn;
  958.  
  959.     if (len > 0)
  960.     {
  961.     Move (rp, XTbase, ROWT(topline));
  962.     Text (rp, Current + Ep->topcolumn, (len > Columns) ? Columns : len);
  963.     }
  964. } /* text_redraw_cmdline */
  965.  
  966.  
  967. /*****************************************************************************
  968.  
  969.     NAME
  970.     do_redisplay
  971.  
  972.     PARAMETER
  973.     void
  974.  
  975.     RETURN
  976.        void
  977.  
  978.     DESCRIPTION
  979.  
  980. ******************************************************************************/
  981.  
  982. void do_redisplay (void)
  983. {
  984.     text_adjust (TRUE);
  985. } /* do_redisplay */
  986.  
  987.  
  988. /*****************************************************************************
  989.  
  990.     NAME
  991.     text_redisplay
  992.  
  993.     PARAMETER
  994.     void
  995.  
  996.     RETURN
  997.     void
  998.  
  999.     DESCRIPTION
  1000.  
  1001. ******************************************************************************/
  1002.  
  1003. void text_redisplay (void)
  1004. {
  1005.     ED * ep = Ep;
  1006.     RP * rp = ep->win->RPort;
  1007.  
  1008.     if (!Nsu)
  1009.     {
  1010.     if (!globalflags.Comlinemode)
  1011.     {
  1012.         SetAPen (rp, TEXT_BPEN);
  1013.         SetWrMsk (rp, 0xFF);
  1014.  
  1015.         RectFill (rp, Xbase, Ybase, Xpixs, Ypixs);
  1016.     }
  1017.  
  1018.     text_displayseg (0, Lines);
  1019.     }
  1020. } /* text_redisplay */
  1021.  
  1022.  
  1023. /*****************************************************************************
  1024.  
  1025.     NAME
  1026.     text_redisplaycurrline
  1027.  
  1028.     PARAMETER
  1029.     void
  1030.  
  1031.     RETURN
  1032.     void
  1033.  
  1034.     DESCRIPTION
  1035.     Redrenders the current line.
  1036.  
  1037. ******************************************************************************/
  1038.  
  1039. void text_redisplaycurrline (void)
  1040. {
  1041.     ED * ep  = Ep;
  1042.     RP * rp  = ep->win->RPort;
  1043.     int  row = ep->line - ep->topline;
  1044.  
  1045.     if (!Nsu)
  1046.     {
  1047.     if (globalflags.Comlinemode)
  1048.     {
  1049.         text_displayseg (0, Lines);
  1050.     } else {
  1051.         SetAPen (rp, TEXT_BPEN);
  1052.         SetWrMsk (rp, 0xFF);
  1053.         RectFill (rp, Xbase, ROW(row), Xpixs, ROW(row+1)-1);
  1054.  
  1055.         redraw_block (TRUE, ep->line, ep->topcolumn, ep->line,
  1056.             ep->topcolumn + Columns - 1);
  1057.     }
  1058.     }
  1059. } /* text_redisplaycurrline */
  1060.  
  1061.  
  1062. /*****************************************************************************
  1063.  
  1064.     NAME
  1065.     text_write
  1066.  
  1067.     PARAMETER
  1068.     UBYTE * str;
  1069.  
  1070.     RETURN
  1071.     void
  1072.  
  1073.     DESCRIPTION
  1074.     Inserts the string str into the text.
  1075.  
  1076. ******************************************************************************/
  1077.  
  1078. void text_write (UBYTE * str)
  1079. {
  1080.     WORD  len = strlen ((char *)str);
  1081.     WORD  i;
  1082.     ED    * ep  = Ep;
  1083.     RP    * rp  = ep->win->RPort;
  1084.  
  1085.     if (Clen + len >= MAXLINELEN-1)
  1086.     {
  1087.     text_sync ();
  1088.     text_load ();
  1089.     }
  1090.  
  1091.     if (!ep->config.insertmode)
  1092.     {
  1093.     UWORD line, column_start, column_end;
  1094.  
  1095.     if (ep->column + len >= MAXLINELEN-1)
  1096.         goto fail;
  1097.  
  1098.     movmem (str, Current + ep->column, len);
  1099.  
  1100.     /* clear area */
  1101.     line = ep->line - ep->topline;
  1102.     column_start = ep->column - ep->topcolumn;
  1103.     column_end = column_start + len;
  1104.  
  1105.     /* only draw, if we need to (otherwise the screen is refreshed !) */
  1106.     if (column_end < Columns)
  1107.     {
  1108.         SetAPen (rp, TEXT_BPEN);
  1109.         SetWrMsk (rp, TEXT_MASK);       /* don't write over block */
  1110.  
  1111.         /* clear area */
  1112.         RectFill (rp, COL(column_start), ROW(line),
  1113.             COL(column_end)-1, ROW(line+1)-1);
  1114.  
  1115.         /* refresh block */
  1116.         redraw_block (TRUE, ep->line, ep->column, ep->line,
  1117.                 ep->column + len - 1);
  1118.  
  1119.         setpen (ep->line, ep->column);
  1120.     }
  1121.  
  1122.     if (ep->column + len >= Clen)
  1123.         Clen = ep->column + len;
  1124.  
  1125.     Current[Clen] = 0;
  1126.     } else
  1127.     {
  1128.     if (Clen + len >= MAXLINELEN-1)
  1129.         goto fail;
  1130.  
  1131.     movmem (Current + ep->column, Current + ep->column + len,
  1132.         Clen+1-ep->column);
  1133.     movmem (str, Current + ep->column, len);
  1134.     Clen += len;
  1135.  
  1136.     if (len < Columns - (ep->column - ep->topcolumn))
  1137.     {
  1138.         i = ep->line - ep->topline;
  1139.  
  1140.         setpen (ep->line, ep->column);
  1141.  
  1142.         ScrollRaster (rp, -len * Xsize, 0 ,
  1143.         COL(ep->column - ep->topcolumn),
  1144.         ROW(i),
  1145.         Xpixs,
  1146.         ROW(i + 1) - 1);
  1147.  
  1148.         if (Ep->win->WLayer->Flags & LAYERREFRESH)
  1149.         OptimizedRefresh (Ep);
  1150.     }
  1151.  
  1152.     /* update block */
  1153.     if (ActualBlock.type == BT_NORMAL &&
  1154.         (is_inblock (ep->line, ep->column) & BP_INSIDE))
  1155.     {
  1156.         ActualBlock.end_column += len;
  1157.     }
  1158.     }
  1159.  
  1160.     i = ep->column;
  1161.     redraw_lineseg (Current, ROWT(ep->line - ep->topline), i, i+len);
  1162.  
  1163.     ep->column += len;
  1164.  
  1165.     if (ep->column - ep->topcolumn >= Columns)
  1166.     {
  1167.     text_sync ();
  1168.     text_adjust (FALSE);
  1169.     }
  1170.  
  1171. fail:
  1172.     if (!globalflags.Comlinemode)
  1173.     {
  1174.     if (ep->config.wordwrap)
  1175.         do_reformat(0);
  1176.     else if (ep->config.autosplit)
  1177.     {
  1178.         WORD  thislen;        /* Length of this line */
  1179. //          WORD  nextlen;          /* Length of next line */
  1180.         WORD  wordlen;        /* Length of word */
  1181.         char * ptr;
  1182.  
  1183.         /* Check if we have to break */
  1184.         thislen = strlen ((char *)Current);
  1185.  
  1186.         if (thislen > ep->config.margin && ep->column == thislen)
  1187.         {
  1188.         /* Well, lets start.
  1189.            This algorithm is very simple for now. It does work only,
  1190.            when the cursor is the end of the line and copies the last
  1191.            word in the next line.
  1192.         */
  1193.         wordlen = thislen - 1;
  1194.         ptr = (char *)Current + wordlen;
  1195.  
  1196.         while (*ptr != ' ' && wordlen)
  1197.         {
  1198.             ptr --;
  1199.             wordlen --;
  1200.         }
  1201.  
  1202.         /* If we found a space, we are 1 char wrong */
  1203.         if (wordlen)
  1204.         {
  1205.             /* ptr ++; dead assign */
  1206.             wordlen ++;
  1207.         }
  1208.  
  1209.         /* Calc. length of last word */
  1210.         wordlen = thislen - wordlen;
  1211.  
  1212.         /* Do nothing if this word won't fit in the next line */
  1213.         if (wordlen < ep->config.margin)
  1214.         {
  1215.             /* Set cursor at the beginning of the word,
  1216.                split line there, go down and go to last
  1217.                char in this line. */
  1218.             ep->column -= wordlen;
  1219.             do_split ();
  1220.             do_down ();
  1221.             do_lastcolumn ();
  1222.         } /* if does word fit */
  1223.         } /* if "Do we have to split ?" */
  1224.     } /* if Autosplit */
  1225.     } /* if !Comlinemode */
  1226. } /* text_write */
  1227.  
  1228.  
  1229. /*****************************************************************************
  1230.  
  1231.     NAME
  1232.     text_redrawblock
  1233.  
  1234.     PARAMETER
  1235.     BOOL on;    Turn block on (TRUE) or off (FALSE)
  1236.  
  1237.     RETURN
  1238.     void
  1239.  
  1240.     DESCRIPTION
  1241.     Redraw the block.
  1242.  
  1243. ******************************************************************************/
  1244.  
  1245. void text_redrawblock (BOOL on)
  1246. {
  1247.     ED * saveed = NULL;
  1248.  
  1249.     /* if there is a block that belongs to an editor */
  1250.  
  1251.     if (ActualBlock.ep)
  1252.     {
  1253.     /* change the actual editor, if the editor the block is in and the
  1254.        actual one are not the same */
  1255.  
  1256.     if (ActualBlock.ep != Ep)
  1257.     {
  1258.         saveed = Ep;
  1259.         switch_ed (ActualBlock.ep);
  1260.     }
  1261.  
  1262.     /* redraw the block */
  1263.  
  1264.     displayblock (on);
  1265.  
  1266.     /* if we changed the editor, undo it */
  1267.  
  1268.     if (saveed)
  1269.         switch_ed (saveed);
  1270.     } else if (!on)
  1271.     {
  1272.     /* if we want to turn the block off, do it here */
  1273.  
  1274.     ActualBlock.type = BT_NONE;
  1275.     }
  1276. } /* text_redrawblock */
  1277.  
  1278.  
  1279. /*****************************************************************************
  1280.  
  1281.     NAME
  1282.     redraw_text
  1283.  
  1284.     PARAMETER
  1285.     Line start_line;    Line to start with
  1286.     Line end_line;        Line to end in (not included)
  1287.  
  1288.     RETURN
  1289.     void
  1290.  
  1291.     DESCRIPTION
  1292.     Redraws some lines of text. Only the start-line is included in the
  1293.     update.
  1294.  
  1295. ******************************************************************************/
  1296.  
  1297. void redraw_text (Line start_line, Line end_line)
  1298. {
  1299.     if (start_line < Ep->topline)
  1300.     start_line = Ep->topline;
  1301.  
  1302.     if (end_line > Ep->topline + Lines)
  1303.     end_line = Ep->topline + Lines;
  1304.     if (end_line > Ep->lines)
  1305.     end_line = Ep->lines;
  1306.  
  1307.     for ( ; start_line < end_line; start_line ++)
  1308.     redraw_textline (start_line);
  1309. } /* redraw_text */
  1310.  
  1311.  
  1312. /*****************************************************************************
  1313.  
  1314.     NAME
  1315.     redraw_textline
  1316.  
  1317.     PARAMETER
  1318.     Line line;
  1319.  
  1320.     RETURN
  1321.     void
  1322.  
  1323.     DESCRIPTION
  1324.     Redraws one complete lines of text.
  1325.  
  1326.     NOTES
  1327.     - line must be a valid line from the text.
  1328.     - THIS IS A MACRO !
  1329.  
  1330. ******************************************************************************/
  1331.  
  1332.  
  1333. /*****************************************************************************
  1334.  
  1335.     NAME
  1336.     redraw_textlineseg
  1337.  
  1338.     PARAMETER
  1339.     Line   line;        The line
  1340.     Column start_column;    The column to start in
  1341.     Column end_column;    The column to end with (not included)
  1342.  
  1343.     RETURN
  1344.     void
  1345.  
  1346.     DESCRIPTION
  1347.     Redraws part of a lines in the text. We redraw all text between
  1348.     start_column and end_column including only the former.
  1349.  
  1350.     NOTE
  1351.     If used to update text that traverses a block-border, the colors
  1352.     of the drawn text will be wrong.
  1353.  
  1354. ******************************************************************************/
  1355.  
  1356. void redraw_textlineseg (Line line, Column start_column, Column end_column)
  1357. {
  1358.     setpen (line, start_column);
  1359.  
  1360.     if (line == Ep->line)
  1361.     redraw_lineseg (Current, ROWT(line - Ep->topline),
  1362.         start_column, end_column);
  1363.     else
  1364.     redraw_lineseg (GETTEXT(Ep,line), ROWT(line - Ep->topline),
  1365.         start_column, end_column);
  1366. } /* redraw_textlineseg */
  1367.  
  1368.  
  1369. /*****************************************************************************
  1370.  
  1371.     NAME
  1372.     redraw_lineseg
  1373.  
  1374.     PARAMETER
  1375.     UBYTE * text;        The contents of the line
  1376.     UWORD  y;           y-position to draw at
  1377.     Column    start_column;    The column to start in
  1378.     Column    end_column;    The column to end with (not included)
  1379.  
  1380.     RETURN
  1381.     void
  1382.  
  1383.     DESCRIPTION
  1384.     Redraws part of a lines in the text. We redraw all text between
  1385.     start_column and end_column including only the former.
  1386.  
  1387. ******************************************************************************/
  1388.  
  1389. void redraw_lineseg (UBYTE * text, UWORD y, Column start_column, Column end_column)
  1390. {
  1391.     RP *   rp         = Ep->win->RPort;
  1392.     int    len;
  1393.  
  1394.     if (Nsu) return;
  1395.  
  1396.     /* start-column visible ? */
  1397.  
  1398.     if (start_column < Ep->topcolumn)
  1399.     start_column = Ep->topcolumn;
  1400.  
  1401.     /* end-column visible ? */
  1402.  
  1403.     if (end_column > Ep->topcolumn + Columns)
  1404.     end_column = Ep->topcolumn + Columns;
  1405.  
  1406.     /* outside screen ? */
  1407.  
  1408.     if (start_column > end_column)
  1409.     return;
  1410.  
  1411.     /* get length of line beyond the start-column */
  1412.  
  1413.     len = strlen (text);
  1414.  
  1415.     if (len > end_column)
  1416.     len = end_column;
  1417.  
  1418.     len -= start_column;
  1419.  
  1420.     /* if there is still text ... */
  1421.  
  1422.     if (len > 0)
  1423.     {
  1424.     /* get contents of line at offset */
  1425.     text += start_column;
  1426.  
  1427.     while (*text == ' ' && len)
  1428.     {
  1429.         text ++;
  1430.         len --;
  1431.         start_column ++;
  1432.     }
  1433.  
  1434.     /* draw any text that is still to draw */
  1435.  
  1436.     if (len)
  1437.     {
  1438.         /* set gfxcursor */
  1439.  
  1440.         Move (rp, COLT(start_column - Ep->topcolumn), y);
  1441.  
  1442.         /* draw text */
  1443.  
  1444.         Text (rp, text, len);
  1445.     }
  1446.     }
  1447. } /* redraw_lineseg */
  1448.  
  1449.  
  1450. /******************************************************************************
  1451. *****  ENDE text.c
  1452. ******************************************************************************/
  1453.